package com.yixin.hospital.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.yixin.hospital.common.ApiResult;
import com.yixin.hospital.common.Constant;
import com.yixin.hospital.entity.bo.PageInfo;
import com.yixin.hospital.entity.bo.TemplateDetail;
import com.yixin.hospital.entity.domain.Guidance;
import com.yixin.hospital.entity.domain.Template;
import com.yixin.hospital.entity.dto.req.guidance.GuidanceAddReqDTO;
import com.yixin.hospital.entity.dto.req.visit.VisitStopReqDTO;
import com.yixin.hospital.entity.vo.GuidanceStatusReportsVo;
import com.yixin.hospital.entity.vo.GuidanceWaitingNumVO;
import com.yixin.hospital.entity.vo.ListGuidanceVO;
import com.yixin.hospital.enums.GuidanceStatusEnum;
import com.yixin.hospital.enums.GuidanceTypeEnum;
import com.yixin.hospital.mapper.extend.GuidanceExtendMapper;
import com.yixin.hospital.service.GuidanceService;
import com.yixin.hospital.service.JobOfficeService;
import com.yixin.hospital.service.TemplateService;
import com.yixin.hospital.utils.DateUtil;
import com.yixin.hospital.utils.JwtUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import static com.yixin.hospital.common.Constant.format;
import static com.yixin.hospital.enums.ResponseCodeEnum.NOT_FOUND_TEMPLATE;

@RestController
@RequestMapping("/guidance")
@Api(value = "导诊管理", tags = "导诊管理")
@Slf4j
public class GuidanceController {

    @Resource
    GuidanceService guidanceService;
    @Resource
    GuidanceExtendMapper guidanceExtendMapper;
    @Resource
    TemplateService templateService;
    @Resource
    JobOfficeService jobOfficeService;

    @GetMapping("/list")
    @ApiOperation(value = "导诊列表")
    public ApiResult<?> list(@RequestParam int currentPage, @RequestParam int pageSize,
                             @RequestParam(value = "name", required = false) String name,
                             @RequestParam(value = "deptId", required = true) Long deptId,
                             @RequestParam(value = "workAddressId", required = false) Long workAddressId,
                             @RequestParam(value = "jobOfficeId", required = false) Long jobOfficeId,
                             @RequestParam(value = "status", required = false) Long status) {
        IPage<ListGuidanceVO> listGuidanceVOIPage = guidanceExtendMapper.pageVo(Page.of(currentPage, pageSize), name, deptId, workAddressId, jobOfficeId, status);
        PageInfo<ListGuidanceVO> listGuidanceVOPageInfo = new PageInfo<>();
        BeanUtils.copyProperties(listGuidanceVOIPage, listGuidanceVOPageInfo);
        for (ListGuidanceVO record : listGuidanceVOPageInfo.getRecords()) {
            record.setTypeName(GuidanceTypeEnum.getDesc(record.getType()));
            record.setTemplateDetailList(new Gson().fromJson(record.getDetail().toString(), new TypeToken<List<TemplateDetail>>() {}.getType()));
            Integer betweenMinute = (int) ChronoUnit.MINUTES.between(record.getGuidanceTime(), LocalDateTime.now());
            record.setRemainderTime(betweenMinute < record.getWaitTime() ? record.getWaitTime() - betweenMinute : 0);
            String afterGuidanceTime = DateUtil.toChineseDate(betweenMinute);
            record.setAfterGuidanceTime(afterGuidanceTime);
            if (Objects.nonNull(record.getVisitTime()) || Objects.nonNull(record.getInspectionTime())) {
                Integer waitPayBetweenMinute = (int) ChronoUnit.MINUTES.between(Objects.nonNull(record.getVisitTime()) ? record.getVisitTime() : record.getInspectionTime(), LocalDateTime.now());
                record.setWaitPayTime(DateUtil.toChineseDate(waitPayBetweenMinute));
            }
        }
        return ApiResult.success(listGuidanceVOPageInfo);
    }

    @PostMapping("/addOrUpdate")
    @ApiOperation(value = "添加/编辑")
    public ApiResult<?> add(@Valid @RequestBody GuidanceAddReqDTO guidanceAddReqDTO, HttpServletRequest request) {
        String userName = JwtUtil.getName(request.getHeader(Constant.AUTHORIZATION));
        Long userId = JwtUtil.getUserId(request.getHeader(Constant.AUTHORIZATION));

        Guidance guidance = new Guidance();
        BeanUtils.copyProperties(guidanceAddReqDTO, guidance);
        guidance.setDoctorId(guidanceAddReqDTO.getDoctorId());
        guidance.setSubmitUserId(userId);
        guidance.setCreatedBy(userName);
        guidance.setUpdatedBy(userName);
        // add
        if (Objects.isNull(guidanceAddReqDTO.getId())) {
            LambdaQueryWrapper<Template> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Template::getJobOffice, guidanceAddReqDTO.getJobOfficeId());
            List<Template> templateList = templateService.list(queryWrapper);
            if (CollectionUtil.isEmpty(templateList)) return ApiResult.error(NOT_FOUND_TEMPLATE);
            Template template = templateList.get(0);
            guidance.setTemplateId(template.getId());
            guidance.setDetail(template.getDetail());
            guidance.setStatus(0);
            String code = "JZ" + LocalDateTime.now().format(DateTimeFormatter.ofPattern(format));
            guidance.setGuidanceCode(code);
            guidance.setGuidanceTime(LocalDateTime.now());
            guidanceService.save(guidance);
            return ApiResult.success();
        }
        // edit
        guidance.setIsDetail(1);
        guidance.setDetail(new Gson().toJson(guidanceAddReqDTO.getTemplateDetailList()));
        guidanceService.updateById(guidance);

        return ApiResult.success();
    }

    @GetMapping("/guidance-waiting-number")
    @ApiOperation(value = "部门科室的候诊人数和就诊人数")
    public ApiResult<?> list(@RequestParam(value = "deptId", required = true) Long deptId,
                             @RequestParam(value = "workAddressId", required = false) Long workAddressId,
                             @RequestParam(value = "jobOfficeId", required = false) Long jobOfficeId) {


        // 候诊人数
        List<Guidance> waitingList = guidanceService.list(new QueryWrapper<Guidance>()
                .select("job_office_id as jobOfficeId, count(*) as waitingCount")
                .eq("status", GuidanceStatusEnum.WAITING.getCode())
                .eq("dept_id", deptId)
                .eq("work_address_id", workAddressId)
                .groupBy("job_office_id")

        );
//        Map<Long, Long> waitingMap = waitingList.isEmpty() ? new HashMap<>() : waitingList.stream().collect(Collectors.toMap(Guidance::getJobOfficeId, Guidance::getWaitingCount));

        // 就诊人数
        List<Guidance> doingList = guidanceService.list(new QueryWrapper<Guidance>()
                .select("job_office_id as jobOfficeId, count(*) as doingCount")
                .eq("status", GuidanceStatusEnum.VISITING.getCode())
                .eq("dept_id", deptId)
                .eq("work_address_id", workAddressId)
                .groupBy("job_office_id")

        );
//        Map<Long, Long> doingMap = doingList.isEmpty() ? new HashMap<>() : doingList.stream().collect(Collectors.toMap(Guidance::getJobOfficeId, Guidance::getDoingCount));

        List<GuidanceWaitingNumVO> guidanceWaitingNumVOList = new ArrayList<>();
//        for (Map.Entry<Long, Long> entry : waitingMap.entrySet()) {
//            GuidanceWaitingNumVO guidanceWaitingNumVO = new GuidanceWaitingNumVO();
//            Long key = entry.getKey();
//            guidanceWaitingNumVO.setJobOfficeId(key);
//            guidanceWaitingNumVO.setJobOfficeName(jobOfficeService.getById(key).getName());
//            guidanceWaitingNumVO.setWaitingCount(entry.getValue());
//            if (doingMap.containsKey(key)) {
//                guidanceWaitingNumVO.setDoingCount(doingMap.get(key));
//            }
//            guidanceWaitingNumVOList.add(guidanceWaitingNumVO);
//        }

        if (jobOfficeId != null && !guidanceWaitingNumVOList.isEmpty()) {
            List<GuidanceWaitingNumVO> collect = guidanceWaitingNumVOList.stream().filter(guidanceWaitingNumVO -> guidanceWaitingNumVO.getJobOfficeId().equals(jobOfficeId)).collect(Collectors.toList());
            return ApiResult.success(collect);
        }


        return ApiResult.success(guidanceWaitingNumVOList);
    }

    @PostMapping("/guidance-stop")
    @ApiOperation(value = "终止接口")
    @Transactional
    public ApiResult<?> visitStop(@Valid @RequestBody VisitStopReqDTO visitStopReqDTO, HttpServletRequest request) {
        String userName = JwtUtil.getName(request.getHeader(Constant.AUTHORIZATION));

        Guidance guidance = guidanceService.getOne(new LambdaQueryWrapper<Guidance>().eq(Guidance::getGuidanceCode, visitStopReqDTO.getGuidanceCode()));
        guidance.setStatus(GuidanceStatusEnum.SUSPEND.getCode());
        guidance.setRemark(visitStopReqDTO.getStopRemark());
        guidance.setUpdatedBy(userName);
        guidanceService.updateById(guidance);

        return ApiResult.success();
    }

    @GetMapping("/job-status-list")
    @ApiOperation(value = "部门的各状态就诊人数")
    public ApiResult<?> jobStatusList(@RequestParam(value = "deptId") Long deptId) {
        List<GuidanceStatusReportsVo> list = guidanceExtendMapper.statusReports(deptId);
        return ApiResult.success(list);
    }
}
